package com.lefevre.cms.service.question.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.lefevre.cms.bean.question.QuestionTag;
import com.lefevre.cms.mapper.QuestionTagMapper;
import com.lefevre.cms.service.besa.DaoSupport;
import com.lefevre.cms.service.question.QuestionService;
import com.lefevre.cms.service.question.QuestionTagService;
import com.lefevre.cms.web.action.SystemException;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * 问题标签实现
 *
 * @author Lefevre
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class QuestionTagServiceImpl extends DaoSupport<QuestionTag> implements QuestionTagService {

    @Resource
    QuestionService questionService;
    @Resource
    private QuestionTagMapper baseMapper;

    /**
     * 根据Id查询标签
     *
     * @param questionTagId 标签Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public QuestionTag findById(Long questionTagId) {
        return baseMapper.selectById(questionTagId);
    }

    /**
     * 根据标签查询所有父类标签
     *
     * @param questionTag 标签
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<QuestionTag> findAllParentById(QuestionTag questionTag) {
        List<QuestionTag> tagList = new ArrayList<>();
        //查询所有父类
        if (questionTag.getParentId() > 0L) {
            List<QuestionTag> list = this.findParentById(questionTag.getParentId(), new ArrayList<>());
            tagList.addAll(list);
        }
        //倒转顺序
        Collections.reverse(tagList);
        return tagList;
    }

    /**
     * 根据ID查询标签父类 (递归)
     *
     * @param parentId        父标签ID
     * @param questionTagList 父标签集合
     * @return
     */
    private List<QuestionTag> findParentById(Long parentId, List<QuestionTag> questionTagList) {
        QuestionTag parentTag = this.findById(parentId);
        if (parentTag != null) {
            questionTagList.add(parentTag);
            if (parentTag.getParentId() > 0L) {
                this.findParentById(parentTag.getParentId(), questionTagList);
            }
        }
        return questionTagList;
    }

    /**
     * 根据标签Id查询子标签(下一节点)
     *
     * @param questionTagId 标签Id
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<QuestionTag> findChildTagById(Long questionTagId) {
        return baseMapper.selectList(new LambdaQueryWrapper<QuestionTag>().eq(QuestionTag::getParentId, questionTagId));
    }

    /**
     * 查询所有问题标签
     *
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    public List<QuestionTag> findAllQuestionTag() {
        return baseMapper.selectList(new LambdaQueryWrapper<QuestionTag>().orderByDesc(
                QuestionTag::getSort
        ));
    }

    /**
     * 查询所有问题标签 - 缓存
     *
     * @return
     */
    @Transactional(readOnly = true, propagation = Propagation.NOT_SUPPORTED)
    @Cacheable(value = "findAllQuestionTag_cache", key = "'findAllQuestionTag_default'")
    public List<QuestionTag> findAllQuestionTag_cache() {
        return this.findAllQuestionTag();
    }


    /**
     * 保存标签
     *
     * @param questionTag
     */
    @CacheEvict(value = "findAllQuestionTag_cache", allEntries = true)
    public void saveQuestionTag(QuestionTag questionTag) {

        baseMapper.insert(questionTag);

        //如果不是根节点
        if (!questionTag.getParentId().equals(0L)) {
            //修改父节点叶子节点状态
            // Query query = em.createQuery("update QuestionTag o set o.childNodeNumber=o.childNodeNumber+1 where o.id=?1")
            //         .setParameter(1, questionTag.getParentId());
            questionTag.setChildNodeNumber(questionTag.getChildNodeNumber() + 1);
            int i = baseMapper.updateById(questionTag);
            if (i == 0) {
                throw new SystemException("父节点不存在");
            }
            //验证上级节点原来是根节点才执行
            int j = baseMapper.update(null, new LambdaUpdateWrapper<QuestionTag>()
                    .set(QuestionTag::getChildNodeNumber, 1)
                    .eq(QuestionTag::getId, questionTag.getParentId())
                    .eq(QuestionTag::getChildNodeNumber, 1));
            if (j > 0) {
                //将父节点下的问题转到本节点
                questionService.updateTagId(questionTag.getParentId(), questionTag.getId());
            }
        }
    }


    /**
     * 修改标签
     *
     * @param questionTag
     * @return
     */
    @CacheEvict(value = "findAllQuestionTag_cache", allEntries = true)
    public Integer updateQuestionTag(QuestionTag questionTag) {
        return baseMapper.updateById(questionTag);
    }

    /**
     * 删除标签
     *
     * @param questionTag 标签
     */
    @CacheEvict(value = "findAllQuestionTag_cache", allEntries = true)
    public Integer deleteQuestionTag(QuestionTag questionTag) {
        int i = baseMapper.deleteById(questionTag.getId());
        if (i > 0) {
            //删除问题标签关联
            questionService.deleteQuestionTagAssociation(questionTag.getId());
            if (questionTag.getParentId() > 0L) {
                //将父节点计数减一
                questionTag.setChildNodeNumber(questionTag.getChildNodeNumber() - 1);
                baseMapper.updateById(questionTag);
            }
            this.deleteChildNode(Collections.singletonList(questionTag.getId()));
        }
        return i;
    }


    /**
     * 递归删除所有子节点
     *
     * @param questionTagIdList
     */
    private void deleteChildNode(List<Long> questionTagIdList) {
        List<Long> idList = new ArrayList<>();
        for (Long tagId : questionTagIdList) {
            List<QuestionTag> questionTags = baseMapper.selectList(new LambdaQueryWrapper<QuestionTag>().eq(QuestionTag::getParentId, tagId));
            for (QuestionTag questionTag : questionTags) {
                //删除当前节点
                int s = baseMapper.deleteById(questionTag.getId());
                if (s > 0) {
                    //删除问题标签关联
                    questionService.deleteQuestionTagAssociation(questionTag.getId());
                }
                if (questionTag.getChildNodeNumber() > 0) {
                    idList.add(questionTag.getId());
                }
            }
        }
        if (idList.size() > 0) {
            this.deleteChildNode(idList);
        }
    }
}

